﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Controls.Primitives;
using Microsoft.Phone.Shell;
using Hammock.Web;
using System.Windows.Media.Imaging;
using Hammock;
using System.Xml.Linq;
using System.Windows.Data;
using System.Globalization;
using System.IO;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO.IsolatedStorage;
using ImageTools;
using ImageTools.IO.Gif;
using Microsoft.Phone.Tasks;
using System.Collections;
using System.Threading;
using ControlTiltEffect;
using System.Text.RegularExpressions;
using System.Text;

namespace Tsina
{
    public partial class MainPage : PhoneApplicationPage
    {
        private ObservableCollection<Tweet> tweets = new ObservableCollection<Tweet>();

        private Dictionary<string, ApplicationBarIconButton> barIconButtonCollection = new Dictionary<string, ApplicationBarIconButton>();

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        // Load data for the ViewModel Items
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            TiltEffect.TiltableItems.Add(typeof(MenuItem));

            ScrollViewer scrollViewer = VisualTreeHelper.GetChild(this.tweetsListBox, 0) as ScrollViewer;
            FrameworkElement border = VisualTreeHelper.GetChild(scrollViewer, 0) as FrameworkElement;
            VisualStateGroup scrollStates = VisualStateManager.GetVisualStateGroups(border)[0] as VisualStateGroup;
            scrollStates.CurrentStateChanging += scrollStates_CurrentStateChanging;

            List<ScrollBar> scrollBarList = CommonHelper.GetVisualChildCollection<ScrollBar>(scrollViewer);
            ScrollBar bar = scrollBarList.Where(x => x.Name == "VerticalScrollBar").First();
            bar.Background = new SolidColorBrush(Color.FromArgb(0xff, 0x99, 0x99, 0x99));

            ApplicationBarIconButton button;

            button = new ApplicationBarIconButton(new Uri("/Images/send.png", UriKind.Relative));
            button.Text = "发送";
            button.Click += new EventHandler(sendButton_Click);
            barIconButtonCollection.Add("sendButton", button);

            button = new ApplicationBarIconButton(new Uri("/Images/cancel.png", UriKind.Relative));
            button.Text = "取消";
            button.Click += new EventHandler(cancelButton_Click);
            barIconButtonCollection.Add("cancelButton", button);

            button = new ApplicationBarIconButton(new Uri("/Images/refresh.png", UriKind.Relative));
            button.Text = "刷新";
            button.Click += new EventHandler(refreshButton_Click);
            barIconButtonCollection.Add("refreshButton", button);

            button = new ApplicationBarIconButton(new Uri("/Images/write.png", UriKind.Relative));
            button.Text = "写微博";
            button.Click += new EventHandler(writeButton_Click);
            barIconButtonCollection.Add("writeButton", button);

            button = new ApplicationBarIconButton(new Uri("/Images/sendMessaging.png", UriKind.Relative));
            button.Text = "发短信";
            button.Click += new EventHandler(sendMessagingButton_Click);
            barIconButtonCollection.Add("sendMessagingButton", button);

            ApplicationBarMenuItem logoutMenuItem = new ApplicationBarMenuItem("注销");
            logoutMenuItem.Click += new EventHandler(logoutMenuItem_Click);
            this.ApplicationBar.MenuItems.Add(logoutMenuItem);

            OAuthHelper.AccessProtectedResource(string.Format("http://api.t.sina.com.cn/users/show/{0}.xml", ConfigHelper.UserId), WebMethod.Get, null, GetUserInfoCompleted, null);
            OAuthHelper.AccessProtectedResource("http://api.t.sina.com.cn/statuses/friends_timeline.xml", WebMethod.Get, null, GetTimeLineCompleted, null);
        }

        private void GetUserInfoCompleted(RestRequest request, RestResponse response, object userState)
        {
            XDocument userInfo = XDocument.Parse(response.Content);
        }

        private void GetTimeLineCompleted(RestRequest request, RestResponse response, object userState)
        {
            XDocument xmlDocument = XDocument.Parse(response.Content);
            IEnumerable<XElement> xmlTweets = xmlDocument.Descendants("status");
            foreach (var item in xmlTweets)
            {
                string pictureUrl = string.Empty;
                if (item.Element("original_pic") != null)
                {
                    pictureUrl = item.Element("original_pic").Value;
                }

                string retweetText = string.Empty;
                if (item.Element("retweeted_status") != null)
                {
                    retweetText = "@" + item.Element("retweeted_status").Element("user").Element("screen_name").Value + "：" + item.Element("retweeted_status").Element("text").Value;
                    if (item.Element("retweeted_status").Element("original_pic") != null)
                    {
                        pictureUrl = item.Element("retweeted_status").Element("original_pic").Value;
                    }
                }

                this.tweets.Add(new Tweet(item.Element("user").Element("id").Value, item.Element("user").Element("screen_name").Value, item.Element("id").Value, item.Element("text").Value, retweetText, pictureUrl, DateTimeOffset.ParseExact(item.Element("created_at").Value, "ddd MMM dd H:mm:ss zzzz yyyy", CultureInfo.InvariantCulture)));
            }
            this.Dispatcher.BeginInvoke(() => tweetsListBox.ItemsSource = this.tweets);
        }

        private void tweetTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            this.currentTweet = this.tweetTextBox.Text;
            barIconButtonCollection["sendButton"].IsEnabled = false;
            barIconButtonCollection["cancelButton"].IsEnabled = false;
            barIconButtonCollection["sendMessagingButton"].IsEnabled = false;
            this.tweetTextBox.Foreground = new SolidColorBrush(Color.FromArgb(0xff, 0x99, 0x99, 0x99));
            this.tweetTextBox.Text = "有什么新鲜事？";
        }

        private void tweetTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (FocusManager.GetFocusedElement() == this.tweetTextBox)
            {
                if (this.tweetTextBox.Text == string.Empty)
                {
                    if (barIconButtonCollection["sendButton"].IsEnabled == true)
                    {
                        barIconButtonCollection["sendButton"].IsEnabled = false;
                    }
                    if (barIconButtonCollection["sendMessagingButton"].IsEnabled == true)
                    {
                        barIconButtonCollection["sendMessagingButton"].IsEnabled = false;
                    }
                }
                else
                {
                    if (barIconButtonCollection["sendButton"].IsEnabled == false)
                    {
                        barIconButtonCollection["sendButton"].IsEnabled = true;
                    }
                    if (barIconButtonCollection["sendMessagingButton"].IsEnabled == false)
                    {
                        barIconButtonCollection["sendMessagingButton"].IsEnabled = true;
                    }
                }
            }
        }

        private string currentTweet = string.Empty;

        private void tweetTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            barIconButtonCollection["cancelButton"].IsEnabled = true;
            this.tweetTextBox.Text = this.currentTweet;
            this.tweetTextBox.Foreground = new SolidColorBrush(Color.FromArgb(0xff, 0x0, 0x0, 0x0));
            this.tweetTextBox.Select(this.tweetTextBox.Text.Length, 0);
        }

        private void sendButton_Click(object sender, EventArgs e)
        {
            List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
            postData.Add(new KeyValuePair<string, string>("status", this.tweetTextBox.Text));
            OAuthHelper.AccessProtectedResource("http://api.t.sina.com.cn/statuses/update.xml", WebMethod.Post, postData, SendTweetCompleted, null);

            this.tweetTextBox.Text = string.Empty;
        }

        private void SendTweetCompleted(RestRequest request, RestResponse response, object userState)
        {
            XDocument xmlDocument = XDocument.Parse(response.Content);
            XElement xmlTweet = xmlDocument.Element("status");
            string tweetId = xmlTweet.Element("id").Value;

            TweetIdAndRetryTimes data = new TweetIdAndRetryTimes { TweetId = tweetId, RetryTimes = 0 };
            OAuthHelper.AccessProtectedResource(string.Format("http://api.t.sina.com.cn/statuses/friends_timeline.xml?since_id={0}", Int64.Parse(tweets.First().TweetId)), WebMethod.Get, null, CheckSendedTweetCompleted, data);
        }

        private struct TweetIdAndRetryTimes
        {
            public string TweetId;
            public int RetryTimes;
        }

        private void CheckSendedTweetCompleted(RestRequest request, RestResponse response, object userState)
        {
            TweetIdAndRetryTimes data = (TweetIdAndRetryTimes)userState;
            XDocument xmlDocument = XDocument.Parse(response.Content);
            IEnumerable<XElement> xmlTweets = xmlDocument.Descendants("status");
            bool got = false;
            foreach (var item in xmlTweets)
            {
                if (item.Element("id").Value == data.TweetId)
                {
                    got = true;
                    break;
                }
            }

            if (got == true)
            {
                this.Dispatcher.BeginInvoke(
                    () => this.refreshButton_Click(null, null)
                );
            }
            else
            {
                if (data.RetryTimes < 5)
                {
                    Thread.Sleep(3000);
                    data.RetryTimes += data.RetryTimes;
                    OAuthHelper.AccessProtectedResource(string.Format("http://api.t.sina.com.cn/statuses/friends_timeline.xml?since_id={0}", Int64.Parse(tweets.First().TweetId)), WebMethod.Get, null, CheckSendedTweetCompleted, data);
                }
            }
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            this.tweetTextBox.Text = string.Empty;
            this.Focus();
        }

        private LoadingStatus loadingStatus = LoadingStatus.None;

        private enum LoadingStatus
        {
            None,
            LoadingOld,
            LoadingNew
        }

        private object syncObject = new object();

        private void scrollStates_CurrentStateChanging(object sender, VisualStateChangedEventArgs e)
        {
            if (e.NewState.Name == "NotScrolling")
            {
                ScrollViewer scrollViewer = VisualTreeHelper.GetParent(sender as FrameworkElement) as ScrollViewer;
                if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
                {
                    lock (syncObject)
                    {
                        if (loadingStatus == LoadingStatus.None)
                        {
                            loadingStatus = LoadingStatus.LoadingOld;
                        }
                    }

                    if (loadingStatus == LoadingStatus.LoadingOld)
                    {
                        this.loadingProgressBar.IsIndeterminate = true;
                        OAuthHelper.AccessProtectedResource(string.Format("http://api.t.sina.com.cn/statuses/friends_timeline.xml?max_id={0}", Int64.Parse(tweets.Last().TweetId) - 1), WebMethod.Get, null, GetMoreTimeLineCompleted, null);
                    }
                }
                else
                {
                    //this.tweetPivotItem.Header = "middle";
                }
            }
        }

        private void GetMoreTimeLineCompleted(RestRequest request, RestResponse response, object userState)
        {
            XDocument xmlDocument = XDocument.Parse(response.Content);
            IEnumerable<XElement> xmlTweets = xmlDocument.Descendants("status");
            this.Dispatcher.BeginInvoke(
                () =>
                {
                    foreach (var item in xmlTweets)
                    {
                        string pictureUrl = string.Empty;
                        if (item.Element("original_pic") != null)
                        {
                            pictureUrl = item.Element("original_pic").Value;
                        }

                        string retweetText = string.Empty;
                        if (item.Element("retweeted_status") != null)
                        {
                            retweetText = "@" + item.Element("retweeted_status").Element("user").Element("screen_name").Value + "：" + item.Element("retweeted_status").Element("text").Value;
                            if (item.Element("retweeted_status").Element("original_pic") != null)
                            {
                                pictureUrl = item.Element("retweeted_status").Element("original_pic").Value;
                            }
                        }
                        this.tweets.Add(new Tweet(item.Element("user").Element("id").Value, item.Element("user").Element("screen_name").Value, item.Element("id").Value, item.Element("text").Value, retweetText, pictureUrl, DateTimeOffset.ParseExact(item.Element("created_at").Value, "ddd MMM dd H:mm:ss zzzz yyyy", CultureInfo.InvariantCulture)));
                    }
                    this.loadingProgressBar.IsIndeterminate = false;
                    loadingStatus = LoadingStatus.None;
                }
                );
        }

        private void sendMessagingButton_Click(object sender, EventArgs e)
        {
            SmsComposeTask smsComposeTask = new SmsComposeTask();
            smsComposeTask.Body = this.tweetTextBox.Text;
            smsComposeTask.Show();
        }

        private void logoutMenuItem_Click(object sender, EventArgs e)
        {
            IsolatedStorageSettings.ApplicationSettings.Remove(ConfigHelper.AccessTokenString);
            IsolatedStorageSettings.ApplicationSettings.Remove(ConfigHelper.AccessTokenSecretString);
            IsolatedStorageSettings.ApplicationSettings.Remove(ConfigHelper.UserIdString);
            this.NavigationService.Navigate(new Uri("/Authentication.xaml", UriKind.Relative));
        }

        private void refreshButton_Click(object sender, EventArgs e)
        {
            foreach (var item in this.tweets)
            {
                item.UpdateCreatedTimeForShow();
            }

            lock (syncObject)
            {
                if (loadingStatus == LoadingStatus.None)
                {
                    loadingStatus = LoadingStatus.LoadingNew;
                }
            }

            if (loadingStatus == LoadingStatus.LoadingNew)
            {
                OAuthHelper.AccessProtectedResource(string.Format("http://api.t.sina.com.cn/statuses/friends_timeline.xml?since_id={0}", Int64.Parse(tweets.First().TweetId)), WebMethod.Get, null, GetLatestTimeLineCompleted, null);
            }
        }

        private void GetLatestTimeLineCompleted(RestRequest request, RestResponse response, object userState)
        {
            XDocument xmlDocument = XDocument.Parse(response.Content);
            IEnumerable<XElement> xmlTweets = xmlDocument.Descendants("status").Reverse();
            this.Dispatcher.BeginInvoke(
                () =>
                {
                    foreach (var item in xmlTweets)
                    {
                        string pictureUrl = string.Empty;
                        if (item.Element("original_pic") != null)
                        {
                            pictureUrl = item.Element("original_pic").Value;
                        }

                        string retweetText = string.Empty;
                        if (item.Element("retweeted_status") != null)
                        {
                            retweetText = "@" + item.Element("retweeted_status").Element("user").Element("screen_name").Value + "：" + item.Element("retweeted_status").Element("text").Value;
                            if (item.Element("retweeted_status").Element("original_pic") != null)
                            {
                                pictureUrl = item.Element("retweeted_status").Element("original_pic").Value;
                            }
                        }
                        this.tweets.Insert(0, new Tweet(item.Element("user").Element("id").Value, item.Element("user").Element("screen_name").Value, item.Element("id").Value, item.Element("text").Value, retweetText, pictureUrl, DateTimeOffset.ParseExact(item.Element("created_at").Value, "ddd MMM dd H:mm:ss zzzz yyyy", CultureInfo.InvariantCulture)));
                    }
                    this.loadingProgressBar.IsIndeterminate = false;
                    loadingStatus = LoadingStatus.None;
                }
                );
        }

        private void writeButton_Click(object sender, EventArgs e)
        {
            this.mainPivot.SelectedItem = this.writeTweetPivotItem;
            this.mainPivot.LoadedPivotItem += FocusTweetTextBox;
        }

        private void FocusTweetTextBox(object sender, PivotItemEventArgs e)
        {
            this.tweetTextBox.Focus();
            this.mainPivot.LoadedPivotItem -= FocusTweetTextBox;
        }

        private void Pivot_UnloadedPivotItem(object sender, PivotItemEventArgs e)
        {
            if (e.Item == this.writeTweetPivotItem && FocusManager.GetFocusedElement() == this.tweetTextBox)
            {
                this.Focus();
            }
        }

        private void Pivot_LoadedPivotItem(object sender, PivotItemEventArgs e)
        {
            this.ApplicationBar.Buttons.Clear();
            if (e.Item == this.tweetPivotItem)
            {
                this.ApplicationBar.Buttons.Add(barIconButtonCollection["writeButton"]);
                this.ApplicationBar.Buttons.Add(barIconButtonCollection["refreshButton"]);
            }
            else
            {
                if (e.Item == this.writeTweetPivotItem)
                {
                    barIconButtonCollection["sendButton"].IsEnabled = false;
                    barIconButtonCollection["cancelButton"].IsEnabled = false;
                    barIconButtonCollection["sendMessagingButton"].IsEnabled = false;
                    this.ApplicationBar.Buttons.Add(barIconButtonCollection["sendButton"]);
                    this.ApplicationBar.Buttons.Add(barIconButtonCollection["sendMessagingButton"]);
                    this.ApplicationBar.Buttons.Add(barIconButtonCollection["cancelButton"]);
                }
                else
                {

                }
            }
        }

        private void Tweet_Loaded(object sender, RoutedEventArgs e)
        {
            StackPanel tweetListItem = sender as StackPanel;
            Tweet tweet = tweetListItem.DataContext as Tweet;

            ContextMenu menu = new ContextMenu();
            menu.IsZoomEnabled = false;

            MenuItem item;
            item = new MenuItem();
            item.SetValue(TiltEffect.IsTiltEnabledProperty, true);
            item.Header = "转发";
            item.DataContext = tweet;
            item.Click += new RoutedEventHandler(RetweetItem_Click);
            menu.Items.Add(item);

            if (ConfigHelper.UserId == tweet.UserId)
            {
                item = new MenuItem();
                item.SetValue(TiltEffect.IsTiltEnabledProperty, true);
                item.Header = "删除";
                item.DataContext = tweet;
                item.Click += new RoutedEventHandler(DeleteItem_Click);
                menu.Items.Add(item);
            }

            if (tweet.PictureUrl != string.Empty)
            {
                item = new MenuItem();
                item.SetValue(TiltEffect.IsTiltEnabledProperty, true);
                item.Header = "图片";
                menu.Items.Add(item);
            }

            string tweetText = tweet.TweetText;
            if (tweet.RetweetText != string.Empty)
            {
                tweetText = tweetText + tweet.RetweetText;
            }

            string pattern = @"http://[a-z0-9A-Z\./%:=&\?\+]*";
            Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
            MatchCollection matchCollection = reg.Matches(tweetText);
            if (matchCollection.Count > 0)
            {
                foreach (Match match in matchCollection)
                {
                    if (menu.Items.Where(p => ((p as MenuItem).Header) as string == match.Value).Count() == 0)
                    {
                        item = new MenuItem();
                        item.SetValue(TiltEffect.IsTiltEnabledProperty, true);
                        item.Header = match.Value;
                        menu.Items.Add(item);
                    }
                }
            }

            ContextMenuService.SetContextMenu(tweetListItem, menu);
        }

        private void RetweetItem_Click(object sender, RoutedEventArgs e)
        {
            Tweet tweet = (sender as MenuItem).DataContext as Tweet;
            //if (tweet.)
            //this.retweetTextBlock.Text = tweet.
            this.mainPivot.SelectedItem = this.writeTweetPivotItem;
            this.mainPivot.LoadedPivotItem += FocusTweetTextBox;
        }

        private void DeleteItem_Click(object sender, RoutedEventArgs e)
        {
            Tweet tweet = (sender as MenuItem).DataContext as Tweet;
            OAuthHelper.AccessProtectedResource(string.Format("http://api.t.sina.com.cn/statuses/destroy/{0}.xml", tweet.TweetId), WebMethod.Post, null, null, null);
            this.tweets.Remove(tweet);
        }

        private void TweetText_Loaded(object sender, RoutedEventArgs e)
        {
            TextBlock tweetTextBlock = sender as TextBlock;
            Tweet tweet = tweetTextBlock.DataContext as Tweet;
            string tweetText = tweet.TweetText;

            HightLightUrl(tweetTextBlock, tweet.TweetText, tweetTextBlock.Foreground);

            if (tweet.RetweetText != string.Empty)
            {
                HightLightUrl(tweetTextBlock, " //" + tweet.RetweetText, new SolidColorBrush(Color.FromArgb(0xff, 0x00, 0x20, 0x60)));
            }

            if (tweet.PictureUrl != string.Empty)
            {
                tweetTextBlock.Inlines.Add(new Run() { Text = " 图", Foreground = new SolidColorBrush(Color.FromArgb(0xff, 0xc0, 0x50, 0x4d)) });
            }
        }

        private void HightLightUrl(TextBlock tweetTextBlock, string tweetText, Brush brush)
        {
            string pattern = @"http://[a-z0-9A-Z\./%:=&\?\+]*";
            Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);
            MatchCollection matchCollection = reg.Matches(tweetText);
            if (matchCollection.Count > 0)
            {
                for (int i = 0; i < matchCollection.Count; i++)
                {
                    int begin;
                    if (i == 0)
                    {
                        begin = 0;
                    }
                    else
                    {
                        begin = matchCollection[i - 1].Index + matchCollection[i - 1].Length;
                    }
                    string temp = tweetText.Substring(begin, matchCollection[i].Index - begin);
                    if (string.IsNullOrEmpty(temp) == false)
                    {
                        tweetTextBlock.Inlines.Add(new Run() { Text = temp, Foreground = brush });
                    }
                    tweetTextBlock.Inlines.Add(new Run() { Text = matchCollection[i].Value, Foreground = new SolidColorBrush(Color.FromArgb(0xff, 0x13, 0x64, 0xc4)) });

                    if (i == matchCollection.Count - 1)
                    {
                        int lastBegin = matchCollection[i].Index + matchCollection[i].Length;
                        if (lastBegin <= tweetText.Length - 1)
                        {
                            temp = tweetText.Substring(lastBegin);
                            tweetTextBlock.Inlines.Add(new Run() { Text = temp, Foreground = brush });
                        }
                    }
                }
            }
            else
            {
                tweetTextBlock.Inlines.Add(new Run() { Text = tweetText, Foreground = brush });
            }
        }
    }

    public class Tweet : INotifyPropertyChanged
    {
        public Tweet(string userId, string screenName, string tweetId, string tweetText, string retweetText, string pictureUrl, DateTimeOffset createdTime)
        {
            TweetId = tweetId;
            UserId = userId;
            ScreenName = screenName;
            TweetText = tweetText;
            RetweetText = retweetText;
            PictureUrl = pictureUrl;
            CreatedTime = createdTime;
        }

        public string TweetId
        {
            get;
            private set;
        }

        public string UserId
        {
            get;
            private set;
        }

        public string ScreenName
        {
            get;
            private set;
        }

        public string TweetText
        {
            get;
            private set;
        }

        public string RetweetText
        {
            get;
            private set;
        }

        public string PictureUrl
        {
            get;
            private set;
        }

        public DateTimeOffset CreatedTime
        {
            get;
            private set;
        }

        public string CreatedTimeForShow
        {
            get
            {
                TimeSpan span = DateTimeOffset.Now - this.CreatedTime;
                string formattedTime = string.Empty;

                if (span.TotalHours > 24)
                {
                    formattedTime = this.CreatedTime.ToLocalTime().ToString("M", new CultureInfo("zh-CN"));
                }
                else
                {
                    if (span.TotalMinutes > 60)
                    {
                        formattedTime = string.Format("{0}小时前", ((int)span.TotalHours).ToString());
                    }
                    else
                    {
                        formattedTime = string.Format("{0}分钟前", ((int)span.TotalMinutes).ToString());
                    }
                }
                return formattedTime;
            }
        }

        public void UpdateCreatedTimeForShow()
        {
            this.OnPropertyChanged("CreatedTimeForShow");
        }

        private void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class UserImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string userId = (string)value;
            return ProfileImageCache.GetProfileImage(userId);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class ProfileImageCache
    {
        private static Dictionary<string, BitmapImage> profileImageCache = new Dictionary<string, BitmapImage>();

        private static object syncObject = new object();

        public static BitmapImage GetProfileImage(string userId)
        {
            BitmapImage image;

            lock (syncObject)
            {
                if (profileImageCache.ContainsKey(userId) == true)
                {
                    image = profileImageCache[userId];
                }
                else
                {
                    image = new BitmapImage();
                    profileImageCache.Add(userId, image);

                    ProfileImage profileImage = new ProfileImage(image);
                    OAuthHelper.AccessProtectedResource(string.Format("http://api.t.sina.com.cn/users/show/{0}.xml", userId), WebMethod.Get, null, profileImage.GetUserInfoCompleted, null);
                }
            }

            return image;
        }

        private class ProfileImage
        {
            private BitmapImage image;

            public ProfileImage(BitmapImage bitmapImage)
            {
                this.image = bitmapImage;
            }

            public void GetUserInfoCompleted(RestRequest request, RestResponse response, object userState)
            {
                XDocument userInfo = XDocument.Parse(response.Content);
                string url = userInfo.Element("user").Element("profile_image_url").Value;
                WebClient wc = new WebClient();
                wc.OpenReadCompleted += this.RequestImageCompleted;
                wc.OpenReadAsync(new Uri(url, UriKind.Absolute));
            }

            private void RequestImageCompleted(object sender, OpenReadCompletedEventArgs e)
            {
                Stream reply = (Stream)e.Result;
                string contentType = (sender as WebClient).ResponseHeaders["Content-Type"];

                if (contentType == "image/gif")
                {
                    GifDecoder gifDecoder = new GifDecoder();
                    ExtendedImage img = new ExtendedImage();
                    gifDecoder.Decode(img, reply);
                    WriteableBitmap wb = new WriteableBitmap(img.PixelWidth, img.PixelHeight);
                    for (int i = 0; i < wb.Pixels.Length; i++)
                    {
                        wb.Pixels[i] = CommonHelper.CalcWritableBitmapPixelValue(img.Pixels[i * 4 + 3], img.Pixels[i * 4], img.Pixels[i * 4 + 1], img.Pixels[i * 4 + 2]);
                    }
                    reply = new MemoryStream();
                    wb.SaveJpeg(reply, wb.PixelWidth, wb.PixelHeight, 0, 100);
                }

                this.image.SetSource(reply);
            }
        }
    }
}